﻿using System.ServiceProcess;

namespace DevilBox.WinService;

/// <summary>
/// Windows服务命令行工具
/// </summary>
///
/// <remarks>
/// 用法: winsrv {action} [serviceName]
/// <br />
/// action: query/start/stop/restart
/// <br />
/// start/stop/restart操作成功输出1,失败输出0
/// </remarks>
internal class Program {
    internal static void Main(string[] args) {
        if (args.Length < 2) return;

        var action = args[0];
        var serviceName = args[1];
        switch (action) {
            case "query": Query(serviceName); break;
            case "start": Start(serviceName); break;
            case "stop": Stop(serviceName); break;
            case "restart": Restart(serviceName); break;
        }
    }

    /// <summary>
    /// 查询服务, 输出格式: serviceName|status(多行)
    /// </summary>
    /// <param name="serviceName">服务名称</param>
    private static void Query(string serviceName) {
        var output = string.Join('\n', ServiceController.GetServices()
            .Where(it => it.ServiceName.Contains(serviceName, StringComparison.CurrentCultureIgnoreCase))
            .Select(it => $"{it.ServiceName}|{it.Status}"));
        Console.WriteLine(output);
    }

    private static void Start(string serviceName) {
        try {
            using var service = new ServiceController(serviceName);
            if (service.Status == ServiceControllerStatus.Running) {
                Console.WriteLine(1);
                return;
            }

            if (service.Status != ServiceControllerStatus.StartPending) {
                service.Start();
            }

            service.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(20));
            Console.WriteLine(1);
        } catch (Exception) {
            Console.WriteLine(0);
        }
    }

    private static void Stop(string serviceName) {
        try {
            using var service = new ServiceController(serviceName);
            if (service.Status == ServiceControllerStatus.Stopped) {
                Console.WriteLine(1);
                return;
            }

            if (service.Status != ServiceControllerStatus.StopPending) {
                service.Stop();
            }

            service.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(20));
            Console.WriteLine(1);
        } catch (Exception) {
            Console.WriteLine(0);
        }
    }

    private static void Restart(string serviceName) {
        try {
            using var service = new ServiceController(serviceName);
            if (service.Status == ServiceControllerStatus.Running) {
                service.Stop();
                service.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(20));
            }

            if (service.Status != ServiceControllerStatus.StartPending) {
                service.Start();
            }

            service.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(20));
            Console.WriteLine(1);
        } catch (Exception) {
            Console.WriteLine(0);
        }
    }
}
